#include <Arduino.h>
#include "private/mywifi.h"
#include "private/myfile.h"
#include "private/myconfig.h"
#include "private/mystate.h"
#include "private/myNTP.h"
#include "private/mymqtt.h"
#include "private/BL0942.h"
#include "private/AHT20.h"
#include "private/ota.h"
#include "private/myudp.h"
#include "private/audio.h"
#include "private/codec.h"
#include "private/xzmqtt.h"
#include "private/Asrpro.h"


#include <esp32-hal-ledc.h>
#include "./lv_chazuo/Mylvgl.h"
#include "./lv_chazuo/TFT.h"
#include "./ESP_HT/ESP_HT.h"

int selectAudio;
bool init_success;
int soundplay;
uint8_t starttalk = 0; //开始说话标志位
uint8_t xiaozhirunning;


// put function declarations here:
void Audio_opus_task(void *pvParameters);
void Init_task(void *pvParameters);
void LVGL_Timer_task(void *pvParameters);

void Update_task(void *pvParameters);

BaseType_t ret;
SemaphoreHandle_t huchi; //互斥锁
SemaphoreHandle_t lvgl_sem; //互斥锁
// EventGroupHandle_t InitGroup; //事件标志组



#define BACKLIGHT_PIN 15 // 背光引脚
uint8_t brightness = 0; // 越小越亮


void setup() 
{
    ESPHT_Init();
    TFT_Init();

    ledcSetup(0, 5000, 8);            // 通道0，5kHz，8位分辨率
    ledcAttachPin(BACKLIGHT_PIN, 0);  // 将 GPIO25 绑定到通道0

    /*编写你自己的代码*/
    GoPage();

    for(int i = 0; i< 100;i ++)
    {
        delay(5);
        lv_timer_handler();
    }

    lvgl_sem = xSemaphoreCreateMutex();
    huchi = xSemaphoreCreateMutex();

    // // // put your setup code here, to run once:
    Serial.begin(115200);
    // //初始化外设
    initBL0942();
    // initAHT20();
    initAsrpro();
    
    // initRelay();
    initMicI2SVad();
    initSoundI2S();
    LittleFS_init();

    //加载配置、状态
    loadSound();
    loadDevState();
    loadDevConfig();

    devstate.volume = "20";
    devconfig.ssid = "XQZWLAN";
    devconfig.password = "hzc790790";
    devconfig.mqtt_server = "172.20.10.100";
    // devconfig.ssid = "英东楼322";
    // devconfig.password = "12345678";
    saveDevConfig();

    // 配置网络选项
    connectWifi();      //连接WIFI
    
    initNTP();          //配置NTP，同步设备时间
    initHassMQTT();         //初始化hassMQTT
    getOTA();           //获取xiaozhi端OTA信息
    initXZMQTT();       //初始化xiaozhi端mqtt

    // 等待MQTT连接
    while (1)
    {
        if (!checkHassMQTT())
        {
            Serial.println("HASS MQTT CONNECTING");
        }
        if (!checkXZMQTT())
        {
            Serial.println("XZ MQTT CONNECTING");
        }
        if (checkHassMQTT() && checkXZMQTT())
        {
            break;
        }
        delay(500);
    }
    // configDev();		//配置设备
    //初始化定时器
    timerInit();
    lv_menu_page();
    Serial.printf("Free heap1: %u\n", esp_get_free_heap_size());

    //创建任务
    ret = xTaskCreate(
        Audio_opus_task,   // 任务函数
        "Audio_opus_task", // 任务名称
        30000,    // 堆栈大小
        NULL,    // 任务参数
        7,       // 任务优先级
        NULL     // 任务句柄
    );
    init_success = true;
    Serial.printf("%d\n",ret);
    // // // 创建任务
    // xTaskCreate(
    //     Init_task,   // 任务函数
    //     "Init_task", // 任务名称
    //     8196,    // 堆栈大小
    //     NULL,    // 任务参数
    //     7,       // 任务优先级
    //     NULL     // 任务句柄
    // );
    Serial.printf("Free heap: %u\n", esp_get_free_heap_size());

    xTaskCreate(
        LVGL_Timer_task,   // 任务函数
        "LVGL_Timer_task", // 任务名称
        4096,    // 堆栈大小
        NULL,    // 任务参数
        1,       // 任务优先级
        NULL     // 任务句柄
    );

}

void loop() 
{	
    ESPHT_Read();
    //播放初始化提示音
    if (init_success)
    {
        Serial.printf("run\n");
        soundplay = 1;
        addSoundToBuffer(SOUND_INIT);
        soundplay = -1;
        init_success = false;
    }
    
    if (getAsrproSignal() == HIGH && !xiaozhirunning)
    {
        soundplay = 1;
        addSoundToBuffer(SOUND_WELCOME);
        soundplay = -1;
        vTaskDelay(pdMS_TO_TICKS(1000));
        publishHelloMsg();
    }
    // Serial.printf("Free heap: %u\n", esp_get_free_heap_size());
    vTaskDelay(pdMS_TO_TICKS(1000));
    Serial.println(getDateTime().c_str());
    saveDevState();
    updateNTP();
}

void LVGL_Timer_task(void *pvParameters)
{
    while(1)
    {
        //调用lv_timer_handler()函数，让GUI完成其工作
        lv_timer_handler(); /* let the GUI do its work */
        //延迟5毫秒
        // vTaskDelay(pdMS_TO_TICKS(5));
        vTaskDelay(pdMS_TO_TICKS(5)); 
    }
}


void Audio_opus_task(void *pvParameters)
{
    uint8_t I2Sbuf[FRAME_OUT_SIZE_8];
    uint8_t opusbuf[512];
    uint8_t aesbuf[512];
    uint8_t sendbuf[512];       //发送给服务器的加密音频数据
    unsigned char nonce_bytes[16];
    uint8_t *recvbuf;       //接受服务器返回的加密音频数据
    uint16_t length_recv;
	int ret = 0;
    int encodelength;
    uint8_t encoder; //编码器初始化标志位
    uint8_t decoder; //编码器初始化标志位
    uint8_t aes;    //aes初始化标志位
    

	while (1)
	{
        if (recvhello == 1)         //如果收到hello信息
        {
            Serial.println("========recv hello========");
            xiaozhirunning = 1;
            //创建编码器
            Serial.printf("Free heap before : %u\n", esp_get_free_heap_size());
            
            //初始化aes
            initAES(udpinfo.key);
            aes = 1;
            starttalk = 1;
            if (connectAudioUdp())
            {
                Serial.println("========connect UDP========");
                publishIOTMsg();
                publishIOTUpdateMsg();
                publishListenMsg();
                //发送倾听标志位
                getFlag(1,0);
                if (initOpusEncoder() == 0)
                {
                    Serial.println("========init opus encoder========");
                    encoder = 1;
                    selectAudio = AUDIO_STATE_RECORDSOUND;
                    Serial.println("open mic");
                }
                else
                {
                    Serial.println("init encoder fail");
                    encoder = 0; 
                    selectAudio = AUDIO_STATE_IDLE;
                    starttalk = 0;
                    userover = 1;
                }
            }
            else
            {
                Serial.println("connect UDP fail");
            }
            Serial.printf("Free heap after: %u\n", esp_get_free_heap_size());
            recvhello = 0;
        }
        if (recvstart == 1)         //如果收到tts start信息
        {
            if (checkUdpConnect())      //如果udp已连接
            {
                Serial.println("start decode");
                selectAudio = AUDIO_STATE_DECODESOUND;
            }
            recvstart = 0;
        }
        if (recvstop == 1)         //如果收到tts stop信息
        {
            if (getLengthBuffer() == 0) 
            {
                vTaskDelay(1000);//等待看看是否会收到goodbye,继续对话的前提是用户没有结束
                if (userover)
                {
                    recvstop = 0;//用户主动结束
                }
                else
                {
                    destoryAES();
                    aes = 0;
                    //销毁解码器
                    if (destoryOpusDecoder() == 0)
                    {
                        Serial.println("========destory decoder========");
                        decoder = 0;
                    }
                    Serial.println("stop play");
                    //清理标志位
                    recvstop = 0;
                    initAES(udpinfo.key);
                    aes = 1;
                    
                    Serial.println("========connect UDP========");
                    publishIOTMsg();
                    publishIOTUpdateMsg();
                    publishListenMsg();
                    //
                    getFlag(1,0);
                    if (initOpusEncoder() == 0)
                    {
                        Serial.println("========init opus encoder========");
                        encoder = 1;
                        selectAudio = AUDIO_STATE_RECORDSOUND;
                        starttalk = 1;
                        Serial.println("open mic");
                    }
                    else
                    {
                        Serial.println("init encoder fail");
                        encoder = 0; 
                        selectAudio = AUDIO_STATE_IDLE;
                    }
                }
                
            }
        }                     
        if (soundplay == 1)
        {
            //创建解码器
            if (initOpusDecoder() == 0)
            {
                Serial.println("========init decoder========");
                decoder = 1;
            }
            else
            {
                Serial.println("init decoder fail");
                decoder = 0; 
            }
            selectAudio = AUDIO_STATE_PLAYSOUND;
            soundplay = 0;
        }
        if (soundplay == -1)
        {
            //停止播放
            if (getLengthBuffer() == 0)
            {
                if (destoryOpusDecoder() == 0)
                {
                    Serial.println("========destory decoder========");
                    decoder = 0;
                }
                selectAudio = AUDIO_STATE_IDLE;
                soundplay = 0;
            }

        }
        
        
        if (userover)
        {
            if (starttalk)  //说明正在说话，不应该停止，标志位被错误置1
            {
                Serial.println("userover error");
                userover = 0;
            }
            else
            {
                if (getLengthBuffer() == 0)
                {
                    // vTaskDelay(2000);   //延时等待，防止清理完标志位又被置位
                    Serial.println("=============userover=============");
                    // xSemaphoreTake(lvgl_sem, portMAX_DELAY);
                    // lv_menu_page();
                    // xSemaphoreGive(lvgl_sem);
                    selectAudio = AUDIO_STATE_IDLE;
                    encoder = 0;
                    decoder = 0;
                    recvhello = 0;
                    recvstart = 0;
                    recvstop = 0;
                    soundplay = 0;
                    xiaozhirunning = 0;
                    if (aes == 1)
                    {
                        destoryAES();
                        aes = 0;
                    }
                    resetOpusSequence();
                    destoryOpusDecoder();
                    destoryOpusEncoder();
                    userover = 0;
                    //关闭udp连接
                    closeUdp();
                }
            }
            
        }
        if (selectAudio == AUDIO_STATE_PLAYSOUND && decoder == 1)       //播放声音
        {
            if (getFromBuffer(&recvbuf, &length_recv))
            {
                //opus解码
                ret = decodeOpus(recvbuf, length_recv, I2Sbuf);
                if (ret == -1)
                {
                    Serial.println("opus decode error");
                }
                i2s_write_with_volume(I2Sbuf, ret * 2, devstate.volume.toFloat() / 100);
            }
            // else
            // {
            //     vTaskDelay(pdMS_TO_TICKS(10));
            // }
        }    
        if (selectAudio == AUDIO_STATE_RECORDSOUND && encoder == 1)       //录音
        {
            ret = read60msMic(I2Sbuf);
            if (ret == FRAME_IN_SIZE_8)
            {
                encodelength = encodeOpus(I2Sbuf, FRAME_IN_SIZE_8, opusbuf);
                if (encodelength == -1)
                {
                    Serial.println("encode error");
                }
                //处理nonce
                processNonce(udpinfo.nonce, encodelength, nonce_bytes);
                //aes-ctr 128加密
                if (encryptAESCTR128(nonce_bytes, opusbuf, encodelength, aesbuf) == -1)
                {
                    Serial.println("AESCTR128 encrypt error");
                }
                //拼接数据
                memcpy(sendbuf, nonce_bytes, 16);
                memcpy(sendbuf + 16, aesbuf, encodelength); //aes加密完长度不变
                //发送
                sendUdpData(sendbuf, encodelength + 16);
                ret = 0;                
            }
            if (ret == -1)      //表示检测不到人声
            {

                selectAudio = AUDIO_STATE_IDLE;
                starttalk = 0;
                destoryAES();
                initAES(udpinfo.key); //重新初始化aes
                aes = 1;
                //发送说话标志位
                getFlag(1,1);
                //销毁编码器
                if (destoryOpusEncoder() == 0)
                {
                    Serial.println("========destory encoder========");
                    encoder = 0;
                }
                //创建解码器
                if (initOpusDecoder() == 0)
                {
                    Serial.println("========init decoder========");
                    decoder = 1;
                }
                else
                {
                    Serial.println("init decoder fail");
                    decoder = 0; 
                }
                Serial.println("end talk");
                publishStopMsg();
                Serial.println("stop listen");
                ret = 0;
            }
        }
        if (selectAudio == AUDIO_STATE_DECODESOUND && decoder == 1)     //解码并播放
        {
            if (getFromBuffer(&recvbuf, &length_recv))
            {
                unsigned char nonce_recv[16];
                int length_data = length_recv - 16;
                //拆分数据
                //从recvbuf中提取nonce
                memcpy(nonce_recv, recvbuf, 16);
                //从recvbuf中提取data
                memcpy(aesbuf, (recvbuf + 16), length_data);
                //aes解密
                ret = decryptAESCTR128(nonce_recv, aesbuf, length_data, opusbuf);
                if (ret == -1)
                {
                    Serial.println("AESCTR128 decrypt error");
                }
                //opus解码
                ret = decodeOpus(opusbuf, length_data, I2Sbuf);
                if (ret == -1)
                {
                    Serial.println("opus decode error");
                }
                //写入缓冲区
                // addToAudioBuffer(I2Sbuf, ret * 2);
                i2s_write_with_volume(I2Sbuf, ret * 2,  devstate.volume.toFloat() / 100);
            }
            else
            {
                vTaskDelay(pdMS_TO_TICKS(10));
            }
        }
		vTaskDelay(pdMS_TO_TICKS(1));
    }
    Serial.printf("Free heap: %u\n", esp_get_free_heap_size());

}